#include "layer.h"

using namespace std;


//************************************************************* Constructors

Layer::Layer(int posX, int posY, int widthLayer, int heightLayer,int widthBoundingRectL, int heightBoundingRectL, QImage::Format format){

    widthBoundingRect = widthBoundingRectL;
    heightBoundingRect = heightBoundingRectL;
    setNomLayer("Calque");
    setPos(posX, posY);
    // Creation of an transparent image
    image = new QImage(widthLayer, heightLayer, format);
    for(int i = 0; i < widthLayer; i++){
        for(int j = 0; j < heightLayer; j++){
            image->setPixel(i, j, qRgba(255, 255, 255, 0));
        }
    }
    semaphore = new QSemaphore(1);
}

Layer::Layer(int posX, int posY, int widthLayer, int heightLayer,QImage::Format format){
    widthBoundingRect = widthLayer;
    heightBoundingRect = heightLayer;
    setNomLayer("Calque");
    setPos(posX, posY);
    // Creation of an transparent image
    image = new QImage(widthLayer, heightLayer, format);
    for(int i = 0; i < widthLayer; i++){
        for(int j = 0; j < heightLayer; j++){
            image->setPixel(i, j, qRgba(255, 255, 255, 0));
        }
    }
    semaphore = new QSemaphore(1);
}

Layer::Layer(const QString & fileName){
    image = new QImage(fileName);
    setNomLayer(QString::fromUtf8("Arrière-plan"));
    widthBoundingRect = image->width();
    heightBoundingRect = image->height();
    semaphore = new QSemaphore(1);
}

//************************************************************* Get

QString Layer::getNomLayer(){
    return nomLayer;
}

int Layer::getWidth(){
    return image->width();
}

int Layer::getHeight(){
    return image->height();
}

QImage* Layer::getImage(){
    return image;
}

//************************************************************* Set

void Layer::setNomLayer(QString nomLayer){
   this->nomLayer = nomLayer;
}

void Layer::setImage(QImage* img){
    semaphore->acquire(1);
    delete image;
    image = img;
    semaphore->release(1);
}

void Layer::setSizeBoundingRect(int width, int height){
    semaphore->acquire(1);
    widthBoundingRect = width;
    heightBoundingRect = height;
    semaphore->release(1);
}

//************************************************************* Filter

void Layer::applyFilter(Filter* filter){
    filter->filter(image);
    update(0, 0, widthBoundingRect, heightBoundingRect);
}

//************************************************************* Paint

void Layer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
    int realBeginX = max(0, (int) x());
    int realBeginY = max(0, (int) y());
    int realEndX = min((int) x() + getWidth(), widthBoundingRect);
    int realEndY = min((int) y() + getHeight(), heightBoundingRect);
    int realWidth = realEndX - realBeginX;
    int realHeight = realEndY - realBeginY;

    if(realWidth > 0 && realHeight > 0)    {
        int xImage, yImage, xSource, ySource;
        if(x() < 0){
            xSource = - x();
        }else{
            xSource = 0;
        }
        if(y() < 0){
            ySource = -y();
        }else{
            ySource = 0;
        }
        semaphore->acquire(1);
        painter->drawImage( QRect(xSource, ySource, realWidth, realHeight), *image, QRect(xSource, ySource, realWidth, realHeight));

        semaphore->release(1);
        //painter->drawImage(QRect(xImage, yImage, realWidth, realHeight), *image, QRect(xSource, ySource, realWidth, realHeight));

    }
}


//************************************************************* Copy

Layer* Layer::copy(){
    Layer* layerCopy = new Layer(x(), y(), getWidth(), getHeight());
    for(int i = 0; i < getWidth(); i++){
        for(int j = 0; j < getHeight(); j++){
            QRgb rgb = getImage()->pixel(i, j);
            layerCopy->getImage()->setPixel(i, j, rgb);
        }
    }
    return layerCopy;
}

//************************************************************* Bounding

QRectF Layer::boundingRect() const{
    return QRectF(0, 0, widthBoundingRect, heightBoundingRect);
}


int Layer::getWidthBoundingRect(){
    return widthBoundingRect;
}
int Layer::getHeightBoundingRect(){
    return heightBoundingRect;
}


void Layer::rotate(qreal angle){
    // This methode is to use, only for angle mutiple of 90°
    int xCentre, yCentre;
    xCentre = heightBoundingRect / 2;
    yCentre = heightBoundingRect / 2;

    int xCornerPos1, yCornerPos1, xCornerPos2, yCornerPos2;

    xCornerPos1 = (double) cos(((double) angle) * M_PI / 180.0)*(double) (x() + getWidth()) - (double) sin(((double) angle) * M_PI / 180.0)*(double) (y() + getHeight());
    yCornerPos1= (double) sin(((double) angle) * M_PI / 180.0)*(double) (x() + getWidth()) + (double) cos(((double) angle) * M_PI / 180.0)*(double) (y() + getHeight());

    xCornerPos2 = (double) cos(((double) angle) * M_PI / 180.0)*(double) (x()) - (double) sin(((double) angle) * M_PI / 180.0)*(double) (y());
    yCornerPos2= (double) sin(((double) angle) * M_PI / 180.0)*(double) (x()) + (double) cos(((double) angle) * M_PI / 180.0)*(double) (y());

    if(xCornerPos1 < 0){
        xCornerPos1 = xCornerPos1 + heightBoundingRect;
        xCornerPos2 = xCornerPos2 + heightBoundingRect;
    }
    if(yCornerPos1 < 0){
        yCornerPos1 = yCornerPos1 + widthBoundingRect;
        yCornerPos2 = yCornerPos2 + widthBoundingRect;
    }
    setPos(min(xCornerPos1, xCornerPos2), min(yCornerPos1, yCornerPos2));

    double a = angle * M_PI/180;
    double sina = sin(a);
    double cosa = cos(a);

    image = new QImage(image->transformed(QTransform(cosa, sina, -sina, cosa, 0, 0)));
}

void Layer::MiroirVertical(){
    QImage* tmpImg = new QImage(*image);
    for(int i = 0; i < getWidth(); i++)    {
        for(int j = 0; j < getHeight(); j++)        {
            QRgb rgb = tmpImg->pixel(i, j);
            getImage()->setPixel(i,getHeight()-j-1, rgb);
        }
    }
    delete tmpImg;
}

void Layer::MiroirHorizontal(){
    QImage* tmpImg = new QImage(*image);
    for(int i = 0; i < getWidth(); i++){
        for(int j = 0; j < getHeight(); j++){
            QRgb rgb = tmpImg->pixel(i, j);
            getImage()->setPixel(getWidth()-i-1, j , rgb);
        }
    }
    delete tmpImg;
}

//************************************************************* Etat Layer

void Layer::changeEtatVisible(){
    if (isVisible()){
        setVisible(false);
    }else{
        setVisible(true);
    }
}

void Layer::changeValeurOpacite(int val){
    float res = ((float)val)/100.0;
    this->setOpacity(res);
}


